home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / src / light.c < prev    next >
C/C++ Source or Header  |  1999-02-04  |  27KB  |  859 lines

  1. /* $Id: light.c,v 3.4 1998/03/27 03:37:40 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: light.c,v $
  26.  * Revision 3.4  1998/03/27 03:37:40  brianp
  27.  * fixed G++ warnings
  28.  *
  29.  * Revision 3.3  1998/02/27 00:44:52  brianp
  30.  * fixed an incorrect error message string
  31.  *
  32.  * Revision 3.2  1998/02/08 20:18:20  brianp
  33.  * removed unneeded headers
  34.  *
  35.  * Revision 3.1  1998/02/02 03:09:34  brianp
  36.  * added GL_LIGHT_MODEL_COLOR_CONTROL (separate specular color interpolation)
  37.  *
  38.  * Revision 3.0  1998/01/31 20:54:56  brianp
  39.  * initial rev
  40.  *
  41.  */
  42.  
  43.  
  44. #ifdef PC_HEADER
  45. #include "all.h"
  46. #else
  47. #include <assert.h>
  48. #include <float.h>
  49. #include <math.h>
  50. #include <stdlib.h>
  51. #include "context.h"
  52. #include "light.h"
  53. #include "macros.h"
  54. #include "matrix.h"
  55. #include "mmath.h"
  56. #include "types.h"
  57. #include "vb.h"
  58. #include "xform.h"
  59. #endif
  60.  
  61.  
  62.  
  63. void gl_ShadeModel( GLcontext *ctx, GLenum mode )
  64. {
  65.    if (INSIDE_BEGIN_END(ctx)) {
  66.       gl_error( ctx, GL_INVALID_OPERATION, "glShadeModel" );
  67.       return;
  68.    }
  69.  
  70.    switch (mode) {
  71.       case GL_FLAT:
  72.       case GL_SMOOTH:
  73.          if (ctx->Light.ShadeModel!=mode) {
  74.             ctx->Light.ShadeModel = mode;
  75.             ctx->NewState |= NEW_RASTER_OPS;
  76.          }
  77.          break;
  78.       default:
  79.          gl_error( ctx, GL_INVALID_ENUM, "glShadeModel" );
  80.    }
  81. }
  82.  
  83.  
  84.  
  85. void gl_Lightfv( GLcontext *ctx,
  86.                  GLenum light, GLenum pname, const GLfloat *params,
  87.                  GLint nparams )
  88. {
  89.    GLint l;
  90.  
  91.    (void) nparams;
  92.  
  93.    if (INSIDE_BEGIN_END(ctx)) {
  94.       gl_error( ctx, GL_INVALID_OPERATION, "glLight" );
  95.       return;
  96.    }
  97.  
  98.    l = (GLint) (light - GL_LIGHT0);
  99.  
  100.    if (l<0 || l>=MAX_LIGHTS) {
  101.       gl_error( ctx, GL_INVALID_ENUM, "glLight" );
  102.       return;
  103.    }
  104.  
  105.    switch (pname) {
  106.       case GL_AMBIENT:
  107.          COPY_4V( ctx->Light.Light[l].Ambient, params );
  108.          break;
  109.       case GL_DIFFUSE:
  110.          COPY_4V( ctx->Light.Light[l].Diffuse, params );
  111.          break;
  112.       case GL_SPECULAR:
  113.          COPY_4V( ctx->Light.Light[l].Specular, params );
  114.          break;
  115.       case GL_POSITION:
  116.          /* transform position by ModelView matrix */
  117.          TRANSFORM_POINT( ctx->Light.Light[l].Position, ctx->ModelViewMatrix,
  118.                           params );
  119.          break;
  120.       case GL_SPOT_DIRECTION:
  121.          /* transform direction by inverse modelview */
  122.          {
  123.             GLfloat direction[4];
  124.             direction[0] = params[0];
  125.             direction[1] = params[1];
  126.             direction[2] = params[2];
  127.             direction[3] = 0.0;
  128.             if (ctx->NewModelViewMatrix) {
  129.                gl_analyze_modelview_matrix( ctx );
  130.             }
  131.             gl_transform_vector( ctx->Light.Light[l].Direction,
  132.                                  direction, ctx->ModelViewInv);
  133.          }
  134.          break;
  135.       case GL_SPOT_EXPONENT:
  136.          if (params[0]<0.0 || params[0]>128.0) {
  137.             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
  138.             return;
  139.          }
  140.          if (ctx->Light.Light[l].SpotExponent != params[0]) {
  141.             ctx->Light.Light[l].SpotExponent = params[0];
  142.             gl_compute_spot_exp_table( &ctx->Light.Light[l] );
  143.          }
  144.          break;
  145.       case GL_SPOT_CUTOFF:
  146.          if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) {
  147.             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
  148.             return;
  149.          }
  150.          ctx->Light.Light[l].SpotCutoff = params[0];
  151.          ctx->Light.Light[l].CosCutoff = cos(params[0]*DEG2RAD);
  152.          break;
  153.       case GL_CONSTANT_ATTENUATION:
  154.          if (params[0]<0.0) {
  155.             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
  156.             return;
  157.          }
  158.          ctx->Light.Light[l].ConstantAttenuation = params[0];
  159.          break;
  160.       case GL_LINEAR_ATTENUATION:
  161.          if (params[0]<0.0) {
  162.             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
  163.             return;
  164.          }
  165.          ctx->Light.Light[l].LinearAttenuation = params[0];
  166.          break;
  167.       case GL_QUADRATIC_ATTENUATION:
  168.          if (params[0]<0.0) {
  169.             gl_error( ctx, GL_INVALID_VALUE, "glLight" );
  170.             return;
  171.          }
  172.          ctx->Light.Light[l].QuadraticAttenuation = params[0];
  173.          break;
  174.       default:
  175.          gl_error( ctx, GL_INVALID_ENUM, "glLight" );
  176.          break;
  177.    }
  178.  
  179.    ctx->NewState |= NEW_LIGHTING;
  180. }
  181.  
  182.  
  183.  
  184. void gl_GetLightfv( GLcontext *ctx,
  185.                     GLenum light, GLenum pname, GLfloat *params )
  186. {
  187.    GLint l = (GLint) (light - GL_LIGHT0);
  188.  
  189.    if (l<0 || l>=MAX_LIGHTS) {
  190.       gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
  191.       return;
  192.    }
  193.  
  194.    switch (pname) {
  195.       case GL_AMBIENT:
  196.          COPY_4V( params, ctx->Light.Light[l].Ambient );
  197.          break;
  198.       case GL_DIFFUSE:
  199.          COPY_4V( params, ctx->Light.Light[l].Diffuse );
  200.          break;
  201.       case GL_SPECULAR:
  202.          COPY_4V( params, ctx->Light.Light[l].Specular );
  203.          break;
  204.       case GL_POSITION:
  205.          COPY_4V( params, ctx->Light.Light[l].Position );
  206.          break;
  207.       case GL_SPOT_DIRECTION:
  208.          COPY_3V( params, ctx->Light.Light[l].Direction );
  209.          break;
  210.       case GL_SPOT_EXPONENT:
  211.          params[0] = ctx->Light.Light[l].SpotExponent;
  212.          break;
  213.       case GL_SPOT_CUTOFF:
  214.          params[0] = ctx->Light.Light[l].SpotCutoff;
  215.          break;
  216.       case GL_CONSTANT_ATTENUATION:
  217.          params[0] = ctx->Light.Light[l].ConstantAttenuation;
  218.          break;
  219.       case GL_LINEAR_ATTENUATION:
  220.          params[0] = ctx->Light.Light[l].LinearAttenuation;
  221.          break;
  222.       case GL_QUADRATIC_ATTENUATION:
  223.          params[0] = ctx->Light.Light[l].QuadraticAttenuation;
  224.          break;
  225.       default:
  226.          gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
  227.          break;
  228.    }
  229. }
  230.  
  231.  
  232.  
  233. void gl_GetLightiv( GLcontext *ctx, GLenum light, GLenum pname, GLint *params )
  234. {
  235.    GLint l = (GLint) (light - GL_LIGHT0);
  236.  
  237.    if (l<0 || l>=MAX_LIGHTS) {
  238.       gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
  239.       return;
  240.    }
  241.  
  242.    switch (pname) {
  243.       case GL_AMBIENT:
  244.          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]);
  245.          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]);
  246.          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]);
  247.          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]);
  248.          break;
  249.       case GL_DIFFUSE:
  250.          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]);
  251.          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]);
  252.          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]);
  253.          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]);
  254.          break;
  255.       case GL_SPECULAR:
  256.          params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]);
  257.          params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]);
  258.          params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]);
  259.          params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]);
  260.          break;
  261.       case GL_POSITION:
  262.          params[0] = (GLint) ctx->Light.Light[l].Position[0];
  263.          params[1] = (GLint) ctx->Light.Light[l].Position[1];
  264.          params[2] = (GLint) ctx->Light.Light[l].Position[2];
  265.          params[3] = (GLint) ctx->Light.Light[l].Position[3];
  266.          break;
  267.       case GL_SPOT_DIRECTION:
  268.          params[0] = (GLint) ctx->Light.Light[l].Direction[0];
  269.          params[1] = (GLint) ctx->Light.Light[l].Direction[1];
  270.          params[2] = (GLint) ctx->Light.Light[l].Direction[2];
  271.          break;
  272.       case GL_SPOT_EXPONENT:
  273.          params[0] = (GLint) ctx->Light.Light[l].SpotExponent;
  274.          break;
  275.       case GL_SPOT_CUTOFF:
  276.          params[0] = (GLint) ctx->Light.Light[l].SpotCutoff;
  277.          break;
  278.       case GL_CONSTANT_ATTENUATION:
  279.          params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation;
  280.          break;
  281.       case GL_LINEAR_ATTENUATION:
  282.          params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation;
  283.          break;
  284.       case GL_QUADRATIC_ATTENUATION:
  285.          params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation;
  286.          break;
  287.       default:
  288.          gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
  289.          break;
  290.    }
  291. }
  292.  
  293.  
  294.  
  295. /**********************************************************************/
  296. /***                        Light Model                             ***/
  297. /**********************************************************************/
  298.  
  299.  
  300. void gl_LightModelfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
  301. {
  302.    switch (pname) {
  303.       case GL_LIGHT_MODEL_AMBIENT:
  304.          COPY_4V( ctx->Light.Model.Ambient, params );
  305.          break;
  306.       case GL_LIGHT_MODEL_LOCAL_VIEWER:
  307.          if (params[0]==0.0)
  308.             ctx->Light.Model.LocalViewer = GL_FALSE;
  309.          else
  310.             ctx->Light.Model.LocalViewer = GL_TRUE;
  311.          break;
  312.       case GL_LIGHT_MODEL_TWO_SIDE:
  313.          if (params[0]==0.0)
  314.             ctx->Light.Model.TwoSide = GL_FALSE;
  315.          else
  316.             ctx->Light.Model.TwoSide = GL_TRUE;
  317.          break;
  318.       case GL_LIGHT_MODEL_COLOR_CONTROL:
  319.          if (params[0] == (GLfloat) GL_SINGLE_COLOR)
  320.             ctx->Light.Model.ColorControl = GL_SINGLE_COLOR;
  321.          else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR)
  322.             ctx->Light.Model.ColorControl = GL_SEPARATE_SPECULAR_COLOR;
  323.          else
  324.             gl_error( ctx, GL_INVALID_ENUM, "glLightModel(param)" );
  325.          break;
  326.       default:
  327.          gl_error( ctx, GL_INVALID_ENUM, "glLightModel" );
  328.          break;
  329.    }
  330.    ctx->NewState |= NEW_LIGHTING;
  331. }
  332.  
  333.  
  334.  
  335.  
  336. /********** MATERIAL **********/
  337.  
  338.  
  339. /*
  340.  * Given a face and pname value (ala glColorMaterial), compute a bitmask
  341.  * of the targeted material values.
  342.  */
  343. GLuint gl_material_bitmask( GLenum face, GLenum pname )
  344. {
  345.    GLuint bitmask = 0;
  346.  
  347.    /* Make a bitmask indicating what material attribute(s) we're updating */
  348.    switch (pname) {
  349.       case GL_EMISSION:
  350.          bitmask |= FRONT_EMISSION_BIT | BACK_EMISSION_BIT;
  351.          break;
  352.       case GL_AMBIENT:
  353.          bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
  354.          break;
  355.       case GL_DIFFUSE:
  356.          bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
  357.          break;
  358.       case GL_SPECULAR:
  359.          bitmask |= FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT;
  360.          break;
  361.       case GL_SHININESS:
  362.          bitmask |= FRONT_SHININESS_BIT | BACK_SHININESS_BIT;
  363.          break;
  364.       case GL_AMBIENT_AND_DIFFUSE:
  365.          bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
  366.          bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
  367.          break;
  368.       case GL_COLOR_INDEXES:
  369.          bitmask |= FRONT_INDEXES_BIT  | BACK_INDEXES_BIT;
  370.          break;
  371.       default:
  372.          gl_problem(NULL, "Bad param in gl_material_bitmask");
  373.          return 0;
  374.    }
  375.  
  376.    ASSERT( face==GL_FRONT || face==GL_BACK || face==GL_FRONT_AND_BACK );
  377.  
  378.    if (face==GL_FRONT) {
  379.       bitmask &= FRONT_MATERIAL_BITS;
  380.    }
  381.    else if (face==GL_BACK) {
  382.       bitmask &= BACK_MATERIAL_BITS;
  383.    }
  384.  
  385.    return bitmask;
  386. }
  387.  
  388.  
  389.  
  390. /*
  391.  * This is called by glColor() when GL_COLOR_MATERIAL is enabled and
  392.  * called by glMaterial() when GL_COLOR_MATERIAL is disabled.
  393.  */
  394. void gl_set_material( GLcontext *ctx, GLuint bitmask, const GLfloat *params )
  395. {
  396.    struct gl_material *mat;
  397.  
  398.    if (INSIDE_BEGIN_END(ctx)) {
  399.       struct vertex_buffer *VB = ctx->VB;
  400.       /* Save per-vertex material changes in the Vertex Buffer.
  401.        * The update_material function will eventually update the global
  402.        * ctx->Light.Material values.
  403.        */
  404.       mat = VB->Material[VB->Count];
  405.       VB->MaterialMask[VB->Count] |= bitmask;
  406.       VB->MonoMaterial = GL_FALSE;
  407.    }
  408.    else {
  409.       /* just update the global material property */
  410.       mat = ctx->Light.Material;
  411.       ctx->NewState |= NEW_LIGHTING;
  412.    }
  413.  
  414.    if (bitmask & FRONT_AMBIENT_BIT) {
  415.       COPY_4V( mat[0].Ambient, params );
  416.    }
  417.    if (bitmask & BACK_AMBIENT_BIT) {
  418.       COPY_4V( mat[1].Ambient, params );
  419.    }
  420.    if (bitmask & FRONT_DIFFUSE_BIT) {
  421.       COPY_4V( mat[0].Diffuse, params );
  422.    }
  423.    if (bitmask & BACK_DIFFUSE_BIT) {
  424.       COPY_4V( mat[1].Diffuse, params );
  425.    }
  426.    if (bitmask & FRONT_SPECULAR_BIT) {
  427.       COPY_4V( mat[0].Specular, params );
  428.    }
  429.    if (bitmask & BACK_SPECULAR_BIT) {
  430.       COPY_4V( mat[1].Specular, params );
  431.    }
  432.    if (bitmask & FRONT_EMISSION_BIT) {
  433.       COPY_4V( mat[0].Emission, params );
  434.    }
  435.    if (bitmask & BACK_EMISSION_BIT) {
  436.       COPY_4V( mat[1].Emission, params );
  437.    }
  438.    if (bitmask & FRONT_SHININESS_BIT) {
  439.       GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
  440.       if (mat[0].Shininess != shininess) {
  441.          mat[0].Shininess = shininess;
  442.          gl_compute_material_shine_table( &mat[0] );
  443.       }
  444.    }
  445.    if (bitmask & BACK_SHININESS_BIT) {
  446.       GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
  447.       if (mat[1].Shininess != shininess) {
  448.          mat[1].Shininess = shininess;
  449.          gl_compute_material_shine_table( &mat[1] );
  450.       }
  451.    }
  452.    if (bitmask & FRONT_INDEXES_BIT) {
  453.       mat[0].AmbientIndex = params[0];
  454.       mat[0].DiffuseIndex = params[1];
  455.       mat[0].SpecularIndex = params[2];
  456.    }
  457.    if (bitmask & BACK_INDEXES_BIT) {
  458.       mat[1].AmbientIndex = params[0];
  459.       mat[1].DiffuseIndex = params[1];
  460.       mat[1].SpecularIndex = params[2];
  461.    }
  462. }
  463.  
  464.  
  465.  
  466. void gl_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
  467. {
  468.    if (INSIDE_BEGIN_END(ctx)) {
  469.       gl_error( ctx, GL_INVALID_OPERATION, "glColorMaterial" );
  470.       return;
  471.    }
  472.    switch (face) {
  473.       case GL_FRONT:
  474.       case GL_BACK:
  475.       case GL_FRONT_AND_BACK:
  476.          ctx->Light.ColorMaterialFace = face;
  477.          break;
  478.       default:
  479.          gl_error( ctx, GL_INVALID_ENUM, "glColorMaterial(face)" );
  480.          return;
  481.    }
  482.    switch (mode) {
  483.       case GL_EMISSION:
  484.       case GL_AMBIENT:
  485.       case GL_DIFFUSE:
  486.       case GL_SPECULAR:
  487.       case GL_AMBIENT_AND_DIFFUSE:
  488.          ctx->Light.ColorMaterialMode = mode;
  489.          break;
  490.       default:
  491.          gl_error( ctx, GL_INVALID_ENUM, "glColorMaterial(mode)" );
  492.          return;
  493.    }
  494.  
  495.    ctx->Light.ColorMaterialBitmask = gl_material_bitmask( face, mode );
  496. }
  497.  
  498.  
  499.  
  500. /*
  501.  * This is only called via the api_function_table struct or by the
  502.  * display list executor.
  503.  */
  504. void gl_Materialfv( GLcontext *ctx,
  505.                     GLenum face, GLenum pname, const GLfloat *params )
  506. {
  507.    GLuint bitmask;
  508.  
  509.    /* error checking */
  510.    if (face!=GL_FRONT && face!=GL_BACK && face!=GL_FRONT_AND_BACK) {
  511.       gl_error( ctx, GL_INVALID_ENUM, "glMaterial(face)" );
  512.       return;
  513.    }
  514.    switch (pname) {
  515.       case GL_EMISSION:
  516.       case GL_AMBIENT:
  517.       case GL_DIFFUSE:
  518.       case GL_SPECULAR:
  519.       case GL_SHININESS:
  520.       case GL_AMBIENT_AND_DIFFUSE:
  521.       case GL_COLOR_INDEXES:
  522.          /* OK */
  523.          break;
  524.       default:
  525.          gl_error( ctx, GL_INVALID_ENUM, "glMaterial(pname)" );
  526.          return;
  527.    }
  528.  
  529.    /* convert face and pname to a bitmask */
  530.    bitmask = gl_material_bitmask( face, pname );
  531.  
  532.    if (ctx->Light.ColorMaterialEnabled) {
  533.       /* The material values specified by glColorMaterial() can't be */
  534.       /* updated by glMaterial() while GL_COLOR_MATERIAL is enabled! */
  535.       bitmask &= ~ctx->Light.ColorMaterialBitmask;
  536.    }
  537.  
  538.    gl_set_material( ctx, bitmask, params );
  539. }
  540.  
  541.  
  542.  
  543.  
  544. void gl_GetMaterialfv( GLcontext *ctx,
  545.                        GLenum face, GLenum pname, GLfloat *params )
  546. {
  547.    GLuint f;
  548.  
  549.    if (INSIDE_BEGIN_END(ctx)) {
  550.       gl_error( ctx, GL_INVALID_OPERATION, "glGetMaterialfv" );
  551.       return;
  552.    }
  553.    if (face==GL_FRONT) {
  554.       f = 0;
  555.    }
  556.    else if (face==GL_BACK) {
  557.       f = 1;
  558.    }
  559.    else {
  560.       gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
  561.       return;
  562.    }
  563.    switch (pname) {
  564.       case GL_AMBIENT:
  565.          COPY_4V( params, ctx->Light.Material[f].Ambient );
  566.          break;
  567.       case GL_DIFFUSE:
  568.          COPY_4V( params, ctx->Light.Material[f].Diffuse );
  569.          break;
  570.       case GL_SPECULAR:
  571.          COPY_4V( params, ctx->Light.Material[f].Specular );
  572.          break;
  573.       case GL_EMISSION:
  574.          COPY_4V( params, ctx->Light.Material[f].Emission );
  575.          break;
  576.       case GL_SHININESS:
  577.          *params = ctx->Light.Material[f].Shininess;
  578.          break;
  579.       case GL_COLOR_INDEXES:
  580.          params[0] = ctx->Light.Material[f].AmbientIndex;
  581.          params[1] = ctx->Light.Material[f].DiffuseIndex;
  582.          params[2] = ctx->Light.Material[f].SpecularIndex;
  583.          break;
  584.       default:
  585.          gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
  586.    }
  587. }
  588.  
  589.  
  590.  
  591. void gl_GetMaterialiv( GLcontext *ctx,
  592.                        GLenum face, GLenum pname, GLint *params )
  593. {
  594.    GLuint f;
  595.  
  596.    if (INSIDE_BEGIN_END(ctx)) {
  597.       gl_error( ctx, GL_INVALID_OPERATION, "glGetMaterialiv" );
  598.       return;
  599.    }
  600.    if (face==GL_FRONT) {
  601.       f = 0;
  602.    }
  603.    else if (face==GL_BACK) {
  604.       f = 1;
  605.    }
  606.    else {
  607.       gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
  608.       return;
  609.    }
  610.    switch (pname) {
  611.       case GL_AMBIENT:
  612.          params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[0] );
  613.          params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[1] );
  614.          params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[2] );
  615.          params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[3] );
  616.          break;
  617.       case GL_DIFFUSE:
  618.          params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[0] );
  619.          params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[1] );
  620.          params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[2] );
  621.          params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[3] );
  622.          break;
  623.       case GL_SPECULAR:
  624.          params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[0] );
  625.          params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[1] );
  626.          params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[2] );
  627.          params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[3] );
  628.          break;
  629.       case GL_EMISSION:
  630.          params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[0] );
  631.          params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[1] );
  632.          params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[2] );
  633.          params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[3] );
  634.          break;
  635.       case GL_SHININESS:
  636.          *params = ROUNDF( ctx->Light.Material[f].Shininess );
  637.          break;
  638.       case GL_COLOR_INDEXES:
  639.          params[0] = ROUNDF( ctx->Light.Material[f].AmbientIndex );
  640.          params[1] = ROUNDF( ctx->Light.Material[f].DiffuseIndex );
  641.          params[2] = ROUNDF( ctx->Light.Material[f].SpecularIndex );
  642.          break;
  643.       default:
  644.          gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
  645.    }
  646. }
  647.  
  648.  
  649.  
  650.  
  651. /**********************************************************************/
  652. /*****                  Lighting computation                      *****/
  653. /**********************************************************************/
  654.  
  655.  
  656. /*
  657.  * Notes:
  658.  *   When two-sided lighting is enabled we compute the color (or index)
  659.  *   for both the front and back side of the primitive.  Then, when the
  660.  *   orientation of the facet is later learned, we can determine which
  661.  *   color (or index) to use for rendering.
  662.  *
  663.  * Variables:
  664.  *   n = normal vector
  665.  *   V = vertex position
  666.  *   P = light source position
  667.  *   Pe = (0,0,0,1)
  668.  *
  669.  * Precomputed:
  670.  *   IF P[3]==0 THEN
  671.  *       // light at infinity
  672.  *       IF local_viewer THEN
  673.  *           VP_inf_norm = unit vector from V to P      // Precompute
  674.  *       ELSE 
  675.  *           // eye at infinity
  676.  *           h_inf_norm = Normalize( VP + <0,0,1> )     // Precompute
  677.  *       ENDIF
  678.  *   ENDIF
  679.  *
  680.  * Functions:
  681.  *   Normalize( v ) = normalized vector v
  682.  *   Magnitude( v ) = length of vector v
  683.  */
  684.  
  685.  
  686.  
  687. /*
  688.  * Whenever the spotlight exponent for a light changes we must call
  689.  * this function to recompute the exponent lookup table.
  690.  */
  691. void gl_compute_spot_exp_table( struct gl_light *l )
  692. {
  693.    int i;
  694.    double exponent = l->SpotExponent;
  695.    double tmp;
  696.    int clamp = 0;
  697.  
  698.    l->SpotExpTable[0][0] = 0.0;
  699.  
  700.    for (i=EXP_TABLE_SIZE-1;i>0;i--) {
  701.       if (clamp == 0) {
  702.          tmp = pow(i/(double)(EXP_TABLE_SIZE-1), exponent);
  703.          if (tmp < FLT_MIN*100.0) {
  704.             tmp = 0.0;
  705.             clamp = 1;
  706.          }
  707.       }
  708.       l->SpotExpTable[i][0] = tmp;
  709.    }
  710.    for (i=0;i<EXP_TABLE_SIZE-1;i++) {
  711.       l->SpotExpTable[i][1] = l->SpotExpTable[i+1][0] - l->SpotExpTable[i][0];
  712.    }
  713.    l->SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
  714. }
  715.  
  716.  
  717.  
  718. /*
  719.  * Whenever the shininess of a material changes we must call this
  720.  * function to recompute the exponential lookup table.
  721.  */
  722. void gl_compute_material_shine_table( struct gl_material *m )
  723. {
  724.    int i;
  725.    m->ShineTable[0] = 0.0F;
  726.    for (i=1;i<SHINE_TABLE_SIZE;i++) {
  727.       /* just invalidate the table */
  728.       m->ShineTable[i] = -1.0;
  729.    }
  730. }
  731.  
  732.  
  733.  
  734. /*
  735.  * Examine current lighting parameters to determine if the optimized lighting
  736.  * function can be used.
  737.  * Also, precompute some lighting values such as the products of light
  738.  * source and material ambient, diffuse and specular coefficients.
  739.  */
  740. void gl_update_lighting( GLcontext *ctx )
  741. {
  742.    GLint i, side;
  743.    struct gl_light *prev_enabled, *light;
  744.  
  745.    if (!ctx->Light.Enabled) {
  746.       /* If lighting is not enabled, we can skip all this. */
  747.       return;
  748.    }
  749.  
  750.    /* Setup linked list of enabled light sources */
  751.    prev_enabled = NULL;
  752.    ctx->Light.FirstEnabled = NULL;
  753.    for (i=0;i<MAX_LIGHTS;i++) {
  754.       ctx->Light.Light[i].NextEnabled = NULL;
  755.       if (ctx->Light.Light[i].Enabled) {
  756.          if (prev_enabled) {
  757.             prev_enabled->NextEnabled = &ctx->Light.Light[i];
  758.          }
  759.          else {
  760.             ctx->Light.FirstEnabled = &ctx->Light.Light[i];
  761.          }
  762.          prev_enabled = &ctx->Light.Light[i];
  763.       }
  764.    }
  765.  
  766.    /* base color = material_emission + global_ambient * material_ambient */
  767.    for (side=0; side<2; side++) {
  768.       ctx->Light.BaseColor[side][0] = ctx->Light.Material[side].Emission[0]
  769.          + ctx->Light.Model.Ambient[0] * ctx->Light.Material[side].Ambient[0];
  770.       ctx->Light.BaseColor[side][1] = ctx->Light.Material[side].Emission[1]
  771.          + ctx->Light.Model.Ambient[1] * ctx->Light.Material[side].Ambient[1];
  772.       ctx->Light.BaseColor[side][2] = ctx->Light.Material[side].Emission[2]
  773.          + ctx->Light.Model.Ambient[2] * ctx->Light.Material[side].Ambient[2];
  774.       ctx->Light.BaseColor[side][3]
  775.          = MIN2( ctx->Light.Material[side].Diffuse[3], 1.0F );
  776.    }
  777.  
  778.  
  779.    /* Precompute some lighting stuff */
  780.    for (light = ctx->Light.FirstEnabled; light; light = light->NextEnabled) {
  781.       for (side=0; side<2; side++) {
  782.          struct gl_material *mat = &ctx->Light.Material[side];
  783.          /* Add each light's ambient component to base color */
  784.          ctx->Light.BaseColor[side][0] += light->Ambient[0] * mat->Ambient[0];
  785.          ctx->Light.BaseColor[side][1] += light->Ambient[1] * mat->Ambient[1];
  786.          ctx->Light.BaseColor[side][2] += light->Ambient[2] * mat->Ambient[2];
  787.          /* compute product of light's ambient with front material ambient */
  788.          light->MatAmbient[side][0] = light->Ambient[0] * mat->Ambient[0];
  789.          light->MatAmbient[side][1] = light->Ambient[1] * mat->Ambient[1];
  790.          light->MatAmbient[side][2] = light->Ambient[2] * mat->Ambient[2];
  791.          /* compute product of light's diffuse with front material diffuse */
  792.          light->MatDiffuse[side][0] = light->Diffuse[0] * mat->Diffuse[0];
  793.          light->MatDiffuse[side][1] = light->Diffuse[1] * mat->Diffuse[1];
  794.          light->MatDiffuse[side][2] = light->Diffuse[2] * mat->Diffuse[2];
  795.          /* compute product of light's specular with front material specular */
  796.          light->MatSpecular[side][0] = light->Specular[0] * mat->Specular[0];
  797.          light->MatSpecular[side][1] = light->Specular[1] * mat->Specular[1];
  798.          light->MatSpecular[side][2] = light->Specular[2] * mat->Specular[2];
  799.  
  800.          /* VP (VP) = Normalize( Position ) */
  801.          COPY_3V( light->VP_inf_norm, light->Position );
  802.          NORMALIZE_3FV( light->VP_inf_norm );
  803.  
  804.          /* h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
  805.          COPY_3V( light->h_inf_norm, light->VP_inf_norm );
  806.          light->h_inf_norm[2] += 1.0F;
  807.          NORMALIZE_3FV( light->h_inf_norm );
  808.  
  809.          COPY_3V( light->NormDirection, light->Direction );
  810.          NORMALIZE_3FV( light->NormDirection );
  811.  
  812.          /* Compute color index diffuse and specular light intensities */
  813.          light->dli = 0.30F * light->Diffuse[0]
  814.                     + 0.59F * light->Diffuse[1]
  815.                     + 0.11F * light->Diffuse[2];
  816.          light->sli = 0.30F * light->Specular[0]
  817.                     + 0.59F * light->Specular[1]
  818.                     + 0.11F * light->Specular[2];
  819.  
  820.       } /* loop over materials */
  821.    } /* loop over lights */
  822.  
  823.    /* Determine if the fast lighting function can be used */
  824.    ctx->Light.Fast = GL_TRUE;
  825.    if (    ctx->Light.BaseColor[0][0]<0.0F
  826.         || ctx->Light.BaseColor[0][1]<0.0F
  827.         || ctx->Light.BaseColor[0][2]<0.0F
  828.         || ctx->Light.BaseColor[0][3]<0.0F
  829.         || ctx->Light.BaseColor[1][0]<0.0F
  830.         || ctx->Light.BaseColor[1][1]<0.0F
  831.         || ctx->Light.BaseColor[1][2]<0.0F
  832.         || ctx->Light.BaseColor[1][3]<0.0F
  833.         || ctx->Light.Model.LocalViewer
  834.         || ctx->Light.ColorMaterialEnabled) {
  835.       ctx->Light.Fast = GL_FALSE;
  836.    }
  837.    else {
  838.       for (light=ctx->Light.FirstEnabled; light; light=light->NextEnabled) {
  839.          if (   light->Position[3]!=0.0F
  840.              || light->SpotCutoff!=180.0F
  841.              || light->MatDiffuse[0][0]<0.0F
  842.              || light->MatDiffuse[0][1]<0.0F
  843.              || light->MatDiffuse[0][2]<0.0F
  844.              || light->MatSpecular[0][0]<0.0F
  845.              || light->MatSpecular[0][1]<0.0F
  846.              || light->MatSpecular[0][2]<0.0F
  847.              || light->MatDiffuse[1][0]<0.0F
  848.              || light->MatDiffuse[1][1]<0.0F
  849.              || light->MatDiffuse[1][2]<0.0F
  850.              || light->MatSpecular[1][0]<0.0F
  851.              || light->MatSpecular[1][1]<0.0F
  852.              || light->MatSpecular[1][2]<0.0F) {
  853.             ctx->Light.Fast = GL_FALSE;
  854.             break;
  855.          }
  856.       }
  857.    }
  858. }
  859.